const db = require("../models");
const logger = require("../utils/_logger");
const DAO = require("../dao/DAO");
const utils = require("../utils/index");
const Users = db.models.users;
const UserRoles = db.models.userRoles;
const UserDepts = db.models.userDepts;
const UserSettings = db.models.userSettings;



/** 新增|修改 */
async function addOrUpdate(data, cb) {
    if (!data.user_name) return cb({ data: null, code: -1, message: "用户名称为空！" });
    if (!data.nick_name) return cb({ data: null, code: -1, message: "用户昵称为空！" });
    const t = await db.sequelize.transaction();
    let user = {
        nick_name: data.nick_name,
        phone: data.phone,
        email: data.email,
        sex: data.sex || 0,
        status: data.status ?? true,
        remark: data.remark,
    }
    try {
        if (!data.id) { // 新增
            user.user_name = data.user_name;
            user.password = data.password;
            user.status == data.status ?? 1;
            Users.findOne({ where: { user_name: data.user_name } }).then(async _ => {
                if (_ && _.id) return cb({ data: null, code: -1, message: "用户账号已存在！" });
                const _u = await Users.create(user, { transaction: t });
                // 创建用户设置
                await UserSettings.create({ user_id: _u.id }, { transaction: t });
                // 创建用户部门关系
                if (data.parent_id) {
                    await UserDepts.create({ user_id: _u.id, dept_id: data.parent_id }, { transaction: t });
                }
                await t.commit();
                cb({ data: null, code: 1, message: "创建成功！" });
            })
        } else { // 修改
            await Users.update(user, { where: { id: data.id }, transaction: t })
            if (data.parent_id) {
                await UserDepts.update({ dept_id: data.parent_id }, { where: { user_id: data.id }, transaction: t })
            }
            await t.commit();
            cb({ data: null, code: 1, message: "修改成功！" });
        }
    } catch (err) {
        await t.rollback();
        logger.errLog(err);
        cb({ data: null, code: -1, message: "当前网络不稳定，请稍后重试" });
    }
}


/** 新增 */
exports.create = async (req, res) => {
    const pm = req.body;
    if (!pm.password) return cb({ data: null, code: -1, message: "用户密码为空！" });
    addOrUpdate(pm, (data) => {
        res.sendResult(data)
    })
};
/** 更新 */
exports.update = (req, res) => {
    const pm = req.body;
    // 请求验证
    if (!pm.id) return res.sendResult({ data: '', code: -1, message: "ID不能为空！" })
    addOrUpdate(pm, (data) => {
        res.sendResult(data)
    })
};
/** 所有list */
exports.findAll = (req, res) => {
    let pm = {
        page_size: req.body?.page_size ?? 10,
        current_page: req.body?.current_page || 1,
        raw: false,
        attributes: { exclude: ['password'] },
        include: [{ model: db.models.depts, attributes: ["id", "name"], where: req.body?.dept_id ? { id: req.body?.dept_id } : null, through: { attributes: [] } }],
        params: {
            phone: req.body?.phone ? { [db.Op.substring]: req.body?.phone ?? '' } : '',
            user_name: req.body?.user_name ? { [db.Op.substring]: req.body?.user_name ?? '' } : '',
            status: req.body?.status ?? ''
        }
    }
    DAO.list(Users, pm, data => {
        // 数据库设计为多对多，需要处理下数据结构
        data.data.list = data.data.list.map(i => {
            i = JSON.parse(JSON.stringify(i));
            i.dept = i.pure_depts[0];
            delete i.pure_depts;
            return i
        })
        res.sendResult(data)
    })
};

/** 修改密码 */
exports.updatePwd = (req, res) => {
    const pm = req.body;
    // 请求验证
    if (!pm.id) return res.sendResult({ data: '', code: -1, message: "ID不能为空！" });
    if (!pm.pwd) return res.sendResult({ data: '', code: -1, message: "密码不能为空！" });
    DAO.update(Users, { password: pm.pwd }, { id: pm.id }, data => {
        res.sendResult(data)
    })
}
/** 修改个人密码 */
exports.updatePwdSelf = (req, res) => {
    const pm = req.body;
    // 请求验证
    if (!pm.old_pwd) return res.sendResult({ data: '', code: -1, message: "旧密码不能为空！" });
    if (!pm.new_pwd) return res.sendResult({ data: '', code: -1, message: "新密码不能为空！" });
    Users.findOne({ where: { id: req.user.id }, attributes: ['password'] }).then(data => {
        data = data.toJSON();
        if(data.password !== pm.old_pwd) return res.sendResult({ data: '', code: -1, message: "密码错误！" });
        DAO.update(Users, { password: pm.new_pwd }, { id: req.user.id }, data => {
            res.sendResult(data)
        })
    })
}

/** 删除 */
exports.delete = (req, res) => {
    const pm = req.body;
    // 请求验证
    if (!pm.id) return res.sendResult({ data: '', code: -1, message: "ID不能为空！" })
    DAO.delete(Users, { id: pm.id }, data => {
        res.sendResult(data)
    })
};

/** 用户角色 */
exports.findRole = (req, res) => {
    const pm = req.body;
    if (!pm.user_id) return res.sendResult({ data: '', code: -1, message: "ID不能为空！" })
    UserRoles.findAll({ where: { user_id: pm.user_id }, raw: true, attributes: ['role_id'] }).then(list => {
        res.sendResult({ data: list.map(i => i.role_id), code: 0, message: "操作成功！" })
    })
};

/** 保存用户角色 */
exports.saveRole = async (req, res) => {
    const pm = req.body;
    if (!pm.id) return res.sendResult({ data: '', code: -1, message: "ID不能为空！" })
    const t = await db.sequelize.transaction();
    // 先删除再添加
    try {
        await UserRoles.destroy({ where: { user_id: pm.id }, transaction: t });
        await UserRoles.bulkCreate(pm.value.map(item => {
            return { user_id: pm.id, role_id: item }
        }), { transaction: t });
        await t.commit();
        res.sendResult({ data: '', code: 1, message: "保存成功" })
    } catch (err) {
        logger.errLog(err);
        t.rollback();
        res.sendResult({ data: '', code: -1, message: "当前网络不稳定，请稍后重试" })
    }

}

/** 个人信息 */
exports.findOne = (req, res) => {
    Users.findByPk(req.user.id, { attributes: { exclude: ['password', 'deletedAt', 'remark'] }, raw: true }).then(data => {
        res.sendResult({ data, code: 0, message: '操作成功！' })
    })
};

/** 修改个人信息 */
exports.updateInfo = (req, res) => {
    const pm = req.body;
    Users.update({
        sex: pm.sex,
        phone: pm.phone,
        email: pm.email,
        avatar: pm.avatar,
        nick_name: pm.nick_name,
        description: pm.description,
    }, { where: { id: req.user.id } }).then(() => {
        res.sendResult({ data: '', code: 1, message: '修改成功！' })
    })
};
/** 获取验证码 */
exports.getCode = (req, res) => {
    const pm = req.query;
    if (!pm.type || !pm.value) return res.sendResultAto(null, -1, '当前网络不稳定，请稍后重试');
    if (![1, 2].includes(pm.type)) return res.sendResultAto(null, -1, '当前网络不稳定，请稍后重试');
    const sessionId = req.headers["visitor-id"];
    const _code = utils.tools.randomNum();
    if (pm.type == 1) {
        // 校验是否为邮箱
        if (!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(pm.value)) return res.sendResultAto(null, -1, '邮箱格式不正确');
        db.redis.set(pm.value + sessionId, _code, 'EX', 60 * 3); // 3分钟过期
        utils.tools.nodemailer({ type: 'code', content: _code, userName: req.user.nick_name || req.user.nick_name, email: pm.value });
    } else {
        // 校验是否为手机号
        if (!/^1[3456789]\d{9}$/.test(pm.value)) return res.sendResultAto(null, -1, '手机号格式不正确');
        db.redis.set(pm.value + sessionId, _code, 'EX', 60 * 3); // 3分钟过期
        utils.sms.sendTxSmsCode({ phone: pm.value, code: _code })
    }
    res.sendResultAto(null, 1, '验证码已发送');
};

/** 修改电话邮箱 */
exports.updatePhoneOrEmail = (req, res) => {
    const pm = req.body;
    if (!pm.type || !pm.value || !pm.code) return res.sendResultAto(null, -1, '当前网络不稳定，请稍后重试');
    if (![1, 2].includes(pm.type)) return res.sendResultAto(null, -1, '当前网络不稳定，请稍后重试');
    const sessionId = req.headers["visitor-id"];
    db.redis.get(pm.value + sessionId, (err, reply) => {
        if (reply == pm.code) {
            let data = {};
            if (pm.type == 1) {
                data.email = pm.value
            } else if (pm.type == 2) {
                data.phone = pm.value
            }
            Users.update(data, { where: { id: req.user.id } }).then(() => {
                res.sendResultAto(null, 1, '修改成功');
            })
        } else {
            res.sendResultAto(null, -1, '验证码错误');
        }
    });
};